package com.example.image_steganography_library_master;


import com.example.imagesteganographylibrary.Text.AsyncTaskCallback.TextEncodingCallback;
import com.example.imagesteganographylibrary.Text.ImageSteganography;

import com.example.imagesteganographylibrary.Text.TextEncoding;

import com.example.imagesteganographylibrary.Utils.ImageUtil;
import com.example.imagesteganographylibrary.view.ProgressDialog;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.*;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.bundle.IBundleManager;
import ohos.data.rdb.ValuesBucket;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImagePacker;
import ohos.media.image.PixelMap;
import ohos.media.photokit.metadata.AVStorage;
import ohos.utils.IntentConstants;
import ohos.utils.net.Uri;
import java.io.*;


public class Encode extends Ability implements TextEncodingCallback, Component.ClickedListener {

    private static final HiLogLabel LABEL_LOG = new HiLogLabel(0, 0, "Encode");
    public static final int IMAGE_SELECT_REQUEST = 1001;
    //Created variables for UI
    private Text whether_encoded;
    private Image imageView;

    private TextField message;
    private TextField secret_key;
    //Objects needed for encoding
    private TextEncoding textEncoding;
    private ImageSteganography imageSteganography;

    //Bitmaps
    private PixelMap original_image;
    private PixelMap encoded_image;
    private Uri filepath;
    private TaskDispatcher taskDispatcher;
    private String filename = "encoding";
    private ProgressDialog progressDialog;

    /**
     * onStart
     *
     * @param intent Intent
     * */
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_encode);
        whether_encoded = (Text) findComponentById(ResourceTable.Id_whether_encoded);
        imageView = (Image) findComponentById(ResourceTable.Id_imageview);
        message = (TextField) findComponentById(ResourceTable.Id_message);
        secret_key = (TextField) findComponentById(ResourceTable.Id_secret_key);

        Button choose_image_button = (Button) findComponentById(ResourceTable.Id_choose_image_button);
        Button encode_button = (Button) findComponentById(ResourceTable.Id_encode_button);
        Button save_image_button = (Button) findComponentById(ResourceTable.Id_save_image_button);

        checkAndRequestPermissions();
        choose_image_button.setClickedListener(this::onClick);
        encode_button.setClickedListener(this::onClick);
        save_image_button.setClickedListener(this::onClick);
        textEncoding = new TextEncoding(this, this);
        taskDispatcher = getUITaskDispatcher();
    }

    private void saveToInternalStorage(String filename, PixelMap pixelMap) {
        try {
            ValuesBucket valuesBucket = new ValuesBucket();
            valuesBucket.putString(AVStorage.Images.Media.DISPLAY_NAME, filename);
            valuesBucket.putString("relative_path", "DCIM/");
            valuesBucket.putString(AVStorage.Images.Media.MIME_TYPE, "image/JPEG");
            //应用独占
            valuesBucket.putInteger("is_pending", 1);
            DataAbilityHelper helper = DataAbilityHelper.creator(this);
            int id = helper.insert(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, valuesBucket);
            Uri uri = Uri.appendEncodedPathToUri(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, String.valueOf(id));
            //这里需要"w"写权限
            FileDescriptor fd = helper.openFile(uri, "w");
            ImagePacker imagePacker = ImagePacker.create();
            ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
            OutputStream outputStream = new FileOutputStream(fd);
            boolean result = imagePacker.initializePacking(outputStream, packingOptions);
            if (result) {
                result = imagePacker.addImage(pixelMap);
                if (result) {
                    long dataSize = imagePacker.finalizePacking();
                }
            }
            outputStream.flush();
            outputStream.close();
            valuesBucket.clear();
            //解除独占
            valuesBucket.putInteger("is_pending", 0);
            helper.update(uri, valuesBucket, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        taskDispatcher.asyncDispatch(new Runnable() {
            @Override
            public void run() {
                progressDialog.hideDialog();
            }
        });
    }

    /**
     * onStartTextEncoding
     * */
    @Override
    public void onStartTextEncoding() {
        //Whatever you want to do at the start of text encoding
        progressDialog = new ProgressDialog(this);
        progressDialog.showDialog("Encoding Message","Loading, Please Wait...");
    }

    /**
     * onCompleteTextEncoding
     *
     * @param result ImageSteganography
     * */
    @Override
    public void onCompleteTextEncoding(ImageSteganography result) {
        // By the end of textEncoding
        progressDialog.hideDialog();
        whether_encoded.setText("Encodeding");
        if (result != null && result.isEncoded()) {
            encoded_image = result.getEncoded_image();
            imageView.setPixelMap(encoded_image);
        }
    }

    private void checkAndRequestPermissions() {
        if (verifySelfPermission("ohos.permission.READ_USER_STORAGE") != IBundleManager.PERMISSION_GRANTED) {
            if (canRequestPermission("ohos.permission.READ_USER_STORAGE")) {
                requestPermissionsFromUser(new String[]{"ohos.permission.READ_USER_STORAGE"}, 0);
            }
        }
        if (verifySelfPermission("ohos.permission.WRITE_USER_STORAGE") != IBundleManager.PERMISSION_GRANTED) {
            if (canRequestPermission("ohos.permission.WRITE_USER_STORAGE")) {
                requestPermissionsFromUser(new String[]{"ohos.permission.WRITE_USER_STORAGE"}, 0);
            }
        }
    }

    /**
     * onClick
     *
     * @param component Component
     * */
    @Override
    public void onClick(Component component) {

        switch (component.getId()) {
            case ResourceTable.Id_choose_image_button:
                ImageChooser();
                break;
            case ResourceTable.Id_encode_button:
                whether_encoded.setText("");
                if (filepath != null) {
                    if (!message.getText().isEmpty() && !secret_key.getText().isEmpty()) {
                        //ImageSteganography Object instantiation
                        imageSteganography = new ImageSteganography(message.getText(),
                                secret_key.getText(),
                                original_image);
                        //TextEncoding object Instantiation
                        textEncoding = new TextEncoding(Encode.this, Encode.this);
                        //Executing the encoding
                        filename = imageSteganography.getEncrypted_message() + "#";
                        textEncoding.inBack(imageSteganography);
                    }
                }
                break;
            case ResourceTable.Id_save_image_button:
                final PixelMap imgToSave = encoded_image;
                progressDialog = new ProgressDialog(this);
                progressDialog.showDialog("Saving Image","Saving, Please Wait...");
                Thread PerformEncoding = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        saveToInternalStorage(filename, imgToSave);
                    }
                });
                PerformEncoding.start();
                break;
            default:
        }
    }

    private void ImageChooser() {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withAction(IntentConstants.ACTION_CHOOSE)
                .build();
        intent.setType("image/*");
        intent.setOperation(operation);
        startAbilityForResult(intent, IMAGE_SELECT_REQUEST);
    }

    /**
     * onAbilityResult
     *
     * @param resultCode int
     * @param requestCode int
     * @param resultData Intent
     * */
    @Override
    protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
        super.onAbilityResult(requestCode, resultCode, resultData);
        if (requestCode == IMAGE_SELECT_REQUEST && resultData != null && resultData.getUri() != null) {
            filepath = ImageUtil.getPath(resultData.getUri());
            original_image = ImageUtil.getPixMap(this, filepath, 0);
            if (original_image != null) {
                imageView.setPixelMap(original_image);
            }
        }
    }

}
